package pl.szpadel.android.gadu;

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;

import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ImageSpan;
import android.text.style.StyleSpan;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.TextView;

public class ChatListAdapter extends Object implements ListAdapter {

	/////////////////
	// constants
	
	private static final int BKGND_MY_ITEM = Color.WHITE;
	private static final int BKGND_OTHER_ITEM = Color.rgb(0xff, 0xEE, 0x89);
	
	private static final HashMap<String, Integer> mSmileys = new HashMap<String, Integer>();
	static {
		mSmileys.put( ":)",		R.drawable.emo_im_happy);
		mSmileys.put( ":-)",	R.drawable.emo_im_happy);
		mSmileys.put( ":]",		R.drawable.emo_im_happy);
		mSmileys.put( ":-]",	R.drawable.emo_im_happy);
		mSmileys.put( ":(",		R.drawable.emo_im_sad);
		mSmileys.put( ":-(",	R.drawable.emo_im_sad);
		mSmileys.put( ":p",		R.drawable.emo_im_tongue_sticking_out);
		mSmileys.put( ":-p",	R.drawable.emo_im_tongue_sticking_out);
		mSmileys.put( ":P",		R.drawable.emo_im_tongue_sticking_out);
		mSmileys.put( ":-P",	R.drawable.emo_im_tongue_sticking_out);
		mSmileys.put( ":x",		R.drawable.emo_im_lips_are_sealed);
		mSmileys.put( ":-x",	R.drawable.emo_im_lips_are_sealed);
		mSmileys.put( ":/",		R.drawable.emo_im_undecided);
		mSmileys.put( ":-/",	R.drawable.emo_im_undecided);
		mSmileys.put( ":*",		R.drawable.emo_im_kissing);
		mSmileys.put( ":-*",	R.drawable.emo_im_kissing);
		mSmileys.put( ";)",		R.drawable.emo_im_winking);
		mSmileys.put( ";-)",	R.drawable.emo_im_winking);
		mSmileys.put( ":>",		R.drawable.emo_im_laughing);
		mSmileys.put( ":D",		R.drawable.emo_im_laughing);
		mSmileys.put( ":-D",	R.drawable.emo_im_laughing);
		mSmileys.put( "<lol>",	R.drawable.emo_im_laughing);
		mSmileys.put( "8)",		R.drawable.emo_im_cool);
		mSmileys.put( "8-)",	R.drawable.emo_im_cool);
		mSmileys.put( "B)",		R.drawable.emo_im_cool);
		mSmileys.put( "B-)",	R.drawable.emo_im_cool);
		mSmileys.put( "<cwaniak>",		R.drawable.emo_im_cool);
		mSmileys.put( "<cwaniak2>",		R.drawable.emo_im_cool);
		mSmileys.put( ":|",		R.drawable.emo_im_foot_in_mouth);
		mSmileys.put( ":-|",	R.drawable.emo_im_foot_in_mouth);
		mSmileys.put( ":o",		R.drawable.emo_im_surprised);
		mSmileys.put( ":-o",	R.drawable.emo_im_surprised);
		mSmileys.put( "oO",		R.drawable.emo_im_wtf);
		mSmileys.put( "Oo",		R.drawable.emo_im_wtf);
		mSmileys.put( ":$",		R.drawable.emo_im_money_mouth);
		mSmileys.put( ":-$",	R.drawable.emo_im_money_mouth);
		mSmileys.put( ":'(",	R.drawable.emo_im_crying);
		mSmileys.put( ":'-(",	R.drawable.emo_im_crying);
		mSmileys.put( "<beczy>",	R.drawable.emo_im_crying);
	}

	
	/// Associated chat
	ChatManager.Chat mChat;
	
	HashSet<DataSetObserver> mObservers = new HashSet<DataSetObserver>();
	
	/// C-tor. Associates list adapter with chat
	public ChatListAdapter(ChatManager.Chat chat) {
		mChat = chat;
		chat.registerObserver(this);
	}

	@Override
	public int getCount() {
		return mChat.getMessages().size();
	}

	@Override
	public Object getItem(int arg0) {
		return mChat.getMessages().get(arg0);
	}

	@Override
	public long getItemId(int arg0) {
		return 0;
	}

	@Override
	public int getItemViewType(int arg0) {
		return 0;
	}

	@Override
	public View getView(int idx, View convertView, ViewGroup parent) {
		ChatManager.Message message = mChat.getMessages().get(idx);
		
		View v = null;
		// reuse previous view if possible
		if (convertView != null) {
			v = convertView;
		} else {
			LayoutInflater inflater = LayoutInflater.from(parent.getContext());
			v = inflater.inflate(R.layout.chat_list_item, null);
		}
		
		// populate the view
		TextView status = (TextView)v.findViewById(R.id.ChatInfo);
		TextView text = (TextView)v.findViewById(R.id.ChatMessage);
		
		// format status
		String contactName = Long.toString(message.sender);
		Config cfg =  App.getInstance().getConfig(); // current user info
		ContactInfoManager cim = App.getInstance().getContactInfoManager();
		if (cfg.getUin() == message.sender) {
			// sent by me!
			v.setBackgroundColor(BKGND_MY_ITEM);
			
			contactName = (String) parent.getContext().getText(R.string.text_me);
		} else {
			// sent by other part
			v.setBackgroundColor(BKGND_OTHER_ITEM);
			
			ContactInfo ci = cim.getByUin(message.sender);
			if (ci != null) {
				contactName = ci.displayName;
			}
		}
		
		// status text
		SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String date = fmt.format(message.time); 
		String statusText =  contactName + ", " + date;
		
		SpannableStringBuilder statusBuilder = new SpannableStringBuilder(statusText);
		// set the contact name to bold
		statusBuilder.setSpan(new StyleSpan(Typeface.BOLD), 0, contactName.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
		status.setText(statusBuilder);
			
		// format message text
		SpannableStringBuilder messageBuilder = new SpannableStringBuilder(message.text);
		Linkify.addLinks(messageBuilder, Linkify.ALL);
		smilify(messageBuilder, parent.getContext());
		text.setText(messageBuilder);
		text.setMovementMethod(LinkMovementMethod.getInstance());
		
		return v;
		
	}

	/// Adds smileys to text in the builder
	private void smilify(SpannableStringBuilder builder, Context ctx) {
		for (int index = 0; index < builder.length(); index++) {
			// make sure this is not a link, otherwise all the http:// will be displayed as undecided droid
			URLSpan linksHere[] = builder.getSpans(index, index, URLSpan.class);
			if (linksHere.length > 0) {
				break;
			}
			// try matching patterns
			for (Entry<String, Integer> entry : mSmileys.entrySet()) {
				String emoStr = entry.getKey();
				int imageRes = entry.getValue();
				
				int length = emoStr.length();
				if (index + length > builder.length()) {
					continue; // emo reaches past the end of the builder
				}
				
				// try matching 
				if (builder.subSequence(index, index + length).toString().equals(emoStr)) {
					// OK, put a image span here
					builder.setSpan(new ImageSpan(ctx, imageRes), index, index + length,
						Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
					index += length - 1;
					break;
				}
		    }
		}
	}
	
	@Override
	public int getViewTypeCount() {
		return 1;
	}

	@Override
	public boolean hasStableIds() {
		return false;
	}

	@Override
	public boolean isEmpty() {
		return  mChat.getMessages().isEmpty();
	}

	@Override
	public void registerDataSetObserver(DataSetObserver arg0) {
		mObservers.add(arg0);

	}

	@Override
	public void unregisterDataSetObserver(DataSetObserver arg0) {
		mObservers.remove(arg0);
	}

	@Override
	public boolean areAllItemsEnabled() {
		return true;
	}

	@Override
	public boolean isEnabled(int arg0) {
		return true;
	}
	
	/// receives notification form chat
	public void onChanged() {
		for (DataSetObserver o : mObservers) {
			o.onChanged();
		}
	}

}
